
#include "DXUT.h"
#include "SDKmisc.h"

#include <string>
#include <vector>

#include "..\System\ISerializable.h"
#include "..\System\Definitions.h"
#include "..\System\IMappable.h"

using namespace std;


#ifndef IRENDER 
#define IRENDER

namespace Rendering
{
  class IBuffer;
  class ITexture;
  class ILayout;

  namespace Layout
  {
    enum  Usage // see DXGI_FORMAT
    {
      LU_Unknown,
      LU_Position,
      LU_Normal,
      LU_Tangent,
      LU_Binormal,
      LU_Texcoord,
      //LU_IndexDouble, // Is it realy nesessary? We have format for it !!!
      LU_Index,
    };
    enum  UsageGroup 
    {
      LUG_Unknown,
      LUG_Pn,
      LUG_PnNr,
      LUG_PnNrTx,
      LUG_TgBn,
      LUG_PnNrTxTgBn,
      LUG_PnTxNrTgBn,
      LUG_IxDb,
      LUG_Ix,
    };
    enum  Format // see DXGI_FORMAT
    {
      LF_Unknown,
      LF_Float3,
      LF_Float2,
      LF_DWord,
      LF_Word,
      LF_A8R8G8B8,
      LF_L8,
      LF_L16,
    };
    enum  Dimmensions
    {
      LD_Unknown = UNKNOWN_ID_U64,
      LD_U = 0,
      LD_V = 1,
      LD_W = 2,
    };
    static UINT64 GetSize( Format format )
    {
      static UINT64 Size[] = 
      {
        /* LF_Unknown  */ 0 ,
        /* LF_Float3   */ 12,
        /* LF_Float2   */ 8,
        /* LF_DWord    */ 4,      
        /* LF_Word     */ 2, 
        /* LF_A8R8G8B8 */ 4, 
        /* LF_L8       */ 1, 
        /* LF_A16      */ 2, 
      };
      return Size[(int)format];
    }
    static Format GetFormat( Usage usage )
    {
      static Format Format[] = 
      {
        /* LU_Unknown     */ LF_Unknown ,
        /* LU_Position    */ LF_Float3  ,
        /* LU_Normal      */ LF_Float3  ,
        /* LU_Tangent     */ LF_Float3  ,      
        /* LU_Binormal    */ LF_Float3  , 
        /* LU_Texcoord    */ LF_Float2  , 
        /* LU_IndexDouble */ LF_DWord   , 
        /* LU_Index       */ LF_Word    , 
      };
      return Format[(int)usage];
    }
    static char*  GetName( Usage usage )
    {
      static char* Names[] = 
      {
        /* LU_Unknown     */ "Unknown",    
        /* LU_Position    */ "Position",    
        /* LU_Normal      */ "Normal",  
        /* LU_Tangent     */ "Tangent",        
        /* LU_Binormal    */ "Binormal",   
        /* LU_Texcoord    */ "Texcoord",   
        /* LU_IndexDouble */ "IndexDouble",   
        /* LU_Index       */ "Index", 
      };
      return Names[(int)usage];
    }
    class Dimmension : public Serialization::ISerializable
    {
    private:
      vector<UINT64> DimmContainer;
    public:
      Dimmension() { }
      Dimmension( UINT64 lengthU )
      {
        DimmContainer.push_back( lengthU );
      }
      Dimmension( UINT64 lengthU, UINT64 lengthV )
      {
        DimmContainer.push_back( lengthU );
        DimmContainer.push_back( lengthV );
      }
      Dimmension( UINT64 lengthU, UINT64 lengthV, UINT64 lengthW )
      {
        DimmContainer.push_back( lengthU );        
        DimmContainer.push_back( lengthV );
        DimmContainer.push_back( lengthW );
      }
      bool SetDimmensionLength( Dimmensions dimmension, UINT64 length )
      {
        if( dimmension == LD_Unknown ) return false;

        return SetDimmensionLength( (UINT64) dimmension, length );
      }
      bool SetDimmensionLength( UINT64 dimmension, UINT64 length )
      {
        assert( 64>dimmension && Violations::Out_of_range );        

        if( DimmContainer.size() <= dimmension )
        {
          DimmContainer.resize(dimmension + 1);
        }
        DimmContainer[dimmension] = length;
        return true;
      }
      UINT64 GetDimmensionLength( Dimmensions dimmension )
      {
        if( dimmension == LD_Unknown ) return NULL;

        return GetDimmensionLength( (UINT64) dimmension );
      }
      UINT64 GetDimmensionLength( UINT64 dimmension )
      {
        assert( dimmension<DimmContainer.size() && Violations::Out_of_range );

        return DimmContainer[dimmension];
      }
      UINT64 GetDimmensionCount( )
      {
        return DimmContainer.size();
      }
      bool IsValid()
      {
        return DimmContainer.size();
      }
      void Reset()
      {
        DimmContainer.resize(0);
      }
      Dimmension& operator=( const Dimmension& ptr )
      {
        DimmContainer = ptr.DimmContainer;
        return *this;
      }
      UINT64& operator[]( UINT64 index )
      {
        return DimmContainer[index];
      }
      UINT64& at( UINT64 index )
      {
        assert( 64>index && Violations::Out_of_range );        

        if( DimmContainer.size() <= index )
        {
          DimmContainer.resize(index + 1);
        }        
        return DimmContainer[index];
      }
      virtual bool Deserialize (Serialization::IStream *pstream)
      {
        UINT64 Size = 0;
        pstream->Read( &Size, sizeof( UINT64 ) );
        DimmContainer.resize( Size ); 
        for( UINT64 i = 0; i<Size; i++ )
        {
          if( !pstream->Read( &DimmContainer[i], sizeof(UINT64) ) )
          {
            return false;
          }
        }
        return true;
      }
      virtual bool Serialize   (Serialization::IStream *pstream)
      {
        UINT64 Size = DimmContainer.size(); 
        pstream->Write( &Size, sizeof(UINT64) );
        for( UINT64 i = 0; i<Size; i++ )
        {
          if( !pstream->Write( &DimmContainer[i], sizeof(UINT64) ) )
          {
            return false;
          }
        }
        return true;
      }
    };
    class Declaration : public Serialization::ISerializable
    {
    public:
      struct Descriptor : public Serialization::ISerializable
      {
        string Name;
        Layout::Usage Usage; 
        Layout::Format Format;
        virtual bool Deserialize (Serialization::IStream *pstream)
        {
          Serialization::Serializer::Deserialize(pstream,Name);
          pstream->Read( &Usage,  sizeof( Layout::Usage  ) );
          pstream->Read( &Format, sizeof( Layout::Format ) );
          return true;
        }
        virtual bool Serialize   (Serialization::IStream *pstream)
        {
          Serialization::Serializer::Serialize(pstream,Name);
          pstream->Write( &Usage,  sizeof( Layout::Usage  ) );
          pstream->Write( &Format, sizeof( Layout::Format ) );
          return true;
        }
      };
    private:
      vector<Descriptor> Descriptors;
      UINT64 Size;
    public:
      Declaration() { Size=0; Descriptors.resize(0); };
      
      Declaration(UsageGroup usagegroup) 
        { SetUsageGroup(usagegroup); ProcessSize(); };
      
      Declaration(Usage usage) 
        { _SetUsage(usage); ProcessSize(); };
      Declaration(Usage usage1, Usage usage2) 
        { _SetUsage(usage1); _SetUsage(usage2); ProcessSize(); };
      Declaration(Usage usage1, Usage usage2, Usage usage3) 
        { _SetUsage(usage1); _SetUsage(usage2); _SetUsage(usage3); ProcessSize(); };
      Declaration(Usage usage1, Usage usage2, Usage usage3, Usage usage4 ) 
        { _SetUsage(usage1); _SetUsage(usage2); _SetUsage(usage3); _SetUsage(usage3); ProcessSize(); };
      Declaration(Usage usage1, Usage usage2, Usage usage3, Usage usage4, Usage usage5 ) 
        { _SetUsage(usage1); _SetUsage(usage2); _SetUsage(usage3); _SetUsage(usage3); _SetUsage(usage5); ProcessSize(); };
      
      Declaration(Format format) 
        { _SetFormat(format); ProcessSize(); };
      Declaration(Format format1, Format format2) 
        { _SetFormat(format1); _SetFormat(format2); ProcessSize(); };
      Declaration(Format format1, Format format2, Format format3) 
        { _SetFormat(format1); _SetFormat(format2); _SetFormat(format3); ProcessSize(); };
      Declaration(Format format1, Format format2, Format format3, Format format4 ) 
        { _SetFormat(format1); _SetFormat(format2); _SetFormat(format3); _SetFormat(format3); ProcessSize(); };
      Declaration(Format format1, Format format2, Format format3, Format format4, Format format5 ) 
        { _SetFormat(format1); _SetFormat(format2); _SetFormat(format3); _SetFormat(format3); _SetFormat(format5); ProcessSize(); };
      /*Declaration( Format format... ) 
      { 
        va_list ap;
        va_start(ap, format);
        for(;;)
        {
          Format f = va_arg(ap,Format);
          if( LF_Unknown != f )
          {
            SetFormat(f);
          }
          else
          {
            break;
          }
        }
        ProcessSize();
      };
      Declaration( Format format[] ) 
      { 
        for( int i=0; i<sizeof(format); i++ ) SetFormat(format[i]);
      };      
      Declaration( Format *format ) 
      { 
        while(LF_Unknown != *format) { SetFormat(*(format++));  };
        ProcessSize(); 
      }; */
      void SetFormat(Format format) { Reset(); _SetFormat(format); ProcessSize(); };
      void AddUsageFormat( Usage usage, Format format ) 
      {
        _SetUsageFormat(usage,format);
        ProcessSize();
      }
      void AddFormat( Format format )
      {
        _SetFormat(format); ProcessSize();
      }
      void SetUsageGroup(UsageGroup usagegroup) { Reset(); _SetUsageGroup(usagegroup); ProcessSize(); };
      Declaration& operator=(const Declaration& input)
      {
        this->Descriptors.resize(0);
        for(UINT64 i = 0; i < input.Descriptors.size(); i++)
        {
          Descriptor desc = input.Descriptors[i];
          this->Descriptors.push_back(desc);
        }
        ProcessSize();
        return *this;
      }
      Declaration(const Declaration &input) 
      { 
        Descriptors.resize(input.Descriptors.size()); 
        copy(input.Descriptors.begin(),input.Descriptors.end(),Descriptors.begin());
        ProcessSize(); 
      };    
      vector<Descriptor>* GetDescriptor()  { return &Descriptors; };
      UINT64 GetElementSize(){ return Size; };
      bool IsValid()
      {
        return Descriptors.size();
      }
      void Reset()
      {
        Descriptors.resize(0);
      }

      virtual bool Deserialize (Serialization::IStream *pstream)
      {
        Descriptors.resize(0);
        UINT64 Size = 0;
        pstream->Read(&Size, sizeof(Size) );
        for(UINT64 i = 0; i < Size; i++)
        {
          Descriptor desc;
          desc.Deserialize(pstream);
          //pstream->Read(&desc, sizeof(Descriptor) );
          Descriptors.push_back(desc);
        }
        ProcessSize();
        return true;
      }
      virtual bool Serialize   (Serialization::IStream *pstream)
      {
        UINT64 Size = Descriptors.size();
        pstream->Write(&Size, sizeof(Size) );
        for(UINT64 i = 0; i < Size; i++)
        {
          //pstream->Write(&(Descriptors[i]), sizeof(Descriptor) );
          Descriptors[i].Serialize(pstream);
        }
        return true;
      }
    private:
      void _SetFormat( Format format ) 
      { 
        Descriptor desc;

        if( NULL == Descriptors.size() )
        { 
          desc.Name   = Layout::GetName(LU_Unknown);
          desc.Usage  = Layout::LU_Unknown;
          desc.Format = format;
        }
        else if( 1 == Descriptors.size() )
        {
          Descriptor *pPredDesc = &Descriptors[0];

          desc.Name   = Layout::GetName(LU_Unknown);
          desc.Usage  = Layout::LU_Unknown;
          desc.Format = format;
        }
        else
        {
          desc.Name   = Layout::GetName(LU_Unknown);
          desc.Usage  = Layout::LU_Unknown;
          desc.Format = format;
        }

        Descriptors.push_back(desc);
      };
      void _SetUsage( Usage usage ) 
      { 
        Descriptor desc;

        desc.Name   = Layout::GetName(LU_Unknown);
        desc.Usage  = usage;
        desc.Format = Layout::GetFormat(usage);

        Descriptors.push_back(desc);
      };
      void _SetUsageFormat( Usage usage, Format format ) 
      { 
        Descriptor desc;

        desc.Name   = Layout::GetName(LU_Unknown);
        desc.Usage  = usage;
        desc.Format = format;

        Descriptors.push_back(desc);
      };
      void _SetUsageGroup( UsageGroup usagegroup ) 
      { 
        switch(usagegroup)
        {
        case LUG_Pn: 
          _SetUsage(LU_Position);
          return;
        case LUG_PnNr: 
          _SetUsage(LU_Position);
          _SetUsage(LU_Normal  );
          return;
        case LUG_PnNrTx:
          _SetUsage(LU_Position);
          _SetUsage(LU_Normal  );
          _SetUsage(LU_Texcoord);
          return;
        case LUG_TgBn:
          _SetUsage(LU_Tangent  );
          _SetUsage(LU_Binormal );
          return;
        case LUG_PnNrTxTgBn:
          _SetUsage(LU_Position );
          _SetUsage(LU_Normal   );
          _SetUsage(LU_Texcoord );
          _SetUsage(LU_Tangent  );
          _SetUsage(LU_Binormal );
          return;
        case LUG_PnTxNrTgBn:
          _SetUsage(LU_Position );
          _SetUsage(LU_Texcoord );
          _SetUsage(LU_Normal   );
          _SetUsage(LU_Tangent  );
          _SetUsage(LU_Binormal );
          return;
        case LUG_IxDb:
          _SetUsageFormat(LU_Index,LF_DWord);
          return;
        case LUG_Ix:
          _SetUsageFormat(LU_Index,LF_Word);
          return;
        default : return;
        }
      };
      void ProcessSize()
      {
        Size = 0;
        for(UINT i = 0; i < Descriptors.size(); i++) { Size += Layout::GetSize(Descriptors[i].Format); }
      };
    };
    class Descriptor // see D3D10_INPUT_ELEMENT_DESC and D3DVERTEXELEMENT9
    {
    private:
      vector<Declaration> Inputs;
    public:
      Descriptor() { Inputs.resize(0); };
      Descriptor( Declaration input ) { Inputs.push_back(input); };
      Descriptor( Declaration input1, Declaration input2 ) { Inputs.push_back(input1); Inputs.push_back(input2); };
      Descriptor( Declaration input1, Declaration input2, Declaration input3 ) { Inputs.push_back(input1); Inputs.push_back(input2); Inputs.push_back(input3); };
      void SetInput(Declaration input) { Inputs.push_back(input); };
      vector<Declaration>* GetInputs() { return &Inputs; };
    };
  }
  namespace Buffer
  {
    enum Topology
    {
      BT_Unknown,        // Unknown             = 0,
      BT_Point_List,     // D3DPT_POINTLIST     = 1,  
      BT_Line_List,      // D3DPT_LINELIST      = 2,      
      BT_Line_Strip,     // D3DPT_LINESTRIP     = 3,  
      BT_Triangle_List,  // D3DPT_TRIANGLELIST  = 4,  
      BT_Triangle_Strip, // D3DPT_TRIANGLESTRIP = 5,
      BT_Triangle_Fan,   // D3DPT_TRIANGLEFAN   = 6, 
    };
    struct Allign : public Serialization::ISerializable
    {
      UINT64 Byte_Begin;
      UINT64 Byte_End;
      UINT64 Byte_Size;
      UINT64 Element_Begin;
      UINT64 Element_End;
      UINT64 Element_Size;
      UINT64 Single_Element_Size;
      Allign()
      {
        Byte_Begin = NULL;
        Byte_End   = NULL;
        Byte_Size  = NULL;
        Element_Begin  = NULL;
        Element_End    = NULL;
        Element_Size   = NULL;
        Single_Element_Size  = NULL;
      }
      void Innitialize( UINT64 elementOffset, Layout::Declaration *pInput, UINT64 elementCount )
      {
        Single_Element_Size = pInput->GetElementSize();
        
        UINT64 ByteOffset = elementOffset * Single_Element_Size;
        UINT64 ByteSize   = elementCount  * Single_Element_Size;

        Byte_Begin = ByteOffset;
        Byte_End   = ByteOffset+ByteSize;
        Byte_Size  = ByteSize;
        Element_Begin = elementOffset;
        Element_End   = elementOffset+elementCount;
        Element_Size  = Element_End-Element_Begin;
      };
      bool CreateSubAllign(UINT64& elements_offset, UINT64 elements_count,  Buffer::Allign& newAllign )
      {
        newAllign = *this;

        UINT64 SizeInBytes   = newAllign.Single_Element_Size * elements_count;
        UINT64 OffsetInBytes = newAllign.Single_Element_Size * elements_offset; 

        newAllign.Byte_Begin = OffsetInBytes;
        newAllign.Byte_End   = OffsetInBytes + SizeInBytes;
        newAllign.Byte_Size  = SizeInBytes;

        newAllign.Element_Begin = elements_offset;
        newAllign.Element_End   = elements_offset + elements_count;
        newAllign.Element_Size  = elements_count;

        elements_offset += elements_count;

        return true;
      }
      virtual bool Deserialize (Serialization::IStream *pstream)
      {
        return pstream->Read( this, sizeof(Allign) );
      }
      virtual bool Serialize   (Serialization::IStream *pstream)
      {
        return pstream->Write( this, sizeof(Allign) );
      }
    };
    struct Descriptor
    {
      Layout::Declaration  *pInput;
      Buffer::Allign *pAllign;
    };
  }
  namespace Texture
  {
    enum Format
    {
      TF_Unknown,  // Unknown
      TF_A8R8G8B8, 
    };
    struct Allign
    {
      UINT64 Byte_Size;
      UINT64 Single_Element_Size;
    };
    struct Desctiptor
    {
      Layout::Declaration       *pInput;
      Layout::Dimmension  *pDimmension;
      Texture::Allign     *pAllign;
      /*
      UINT64 LOD;
      UINT64 Width;
      UINT64 Height;
      */
    };
  }
  namespace Effect
  {
    struct ParameterDescriptor
    {
      string Name;
      UINT64 Id;
      UINT64 Type;
    };
    struct TechniqueDescriptor
    {
      string Name;
      UINT64 Id;
      UINT64 Passes;
    };
    static UINT64 GetID(char* pname, vector<Effect::ParameterDescriptor>* pparameters )
    {
      for( UINT64 i = 0; i < pparameters->size(); i++ )
      {
        if( 0 == strcmp( pname, pparameters->at(i).Name.c_str() ) )
        {
          return i;
        }
      }
      return NULL;
    }
    static UINT64 GetID(char* pname, vector<Effect::TechniqueDescriptor>* ptechniques )
    {
      for( UINT64 i = 0; i < ptechniques->size(); i++ )
      {
        if( 0 == strcmp( pname, ptechniques->at(i).Name.c_str() ) )
        {
          return i;
        }
      }
      return NULL;
    }
  }
  namespace Render
  {
    /*
    namespace Mapping
    {
      struct Descriptor
      {
        void*  pBuffer;
        UINT64 Size;
      };
    }
    */
    class IResource;
    namespace Resource
    {
      enum Type
      {
        RT_Unknown,
        RT_Buffer,
        RT_SubBuffer,
        RT_Texture,
        RT_SubTexture,
        RT_Effect,
        RT_Layout,
      };
      struct Descriptor
      {
        Type   Type;
        Rendering::Layout::Declaration *pInput;
        Layout::Dimmension Dimmension; // In Element - not in Bytes !!!
        Rendering::Render::IResource *pMasterResource;    // Used to create sub-resources !!!
        Descriptor()
        {
          Type = RT_Unknown;
          pInput = NULL;
          pMasterResource = NULL;
        }
        Descriptor( Rendering::Render::Resource::Type type, Rendering::Layout::Declaration *pinput, UINT64 size )
        {
          Type = type;
          pInput = pinput;
          Dimmension.SetDimmensionLength(0,size);
          pMasterResource = NULL;
        }
        Descriptor( Rendering::Render::Resource::Type type, Rendering::Layout::Declaration *pinput, Rendering::Layout::Dimmension *dimmension )
        {
          Type = type;
          pInput = pinput;
          Dimmension = *dimmension;
          pMasterResource = NULL;
        }
        Descriptor( Rendering::Layout::Declaration *pinput, Rendering::IBuffer *presource , UINT64 size )
        {
          Type = RT_Buffer;
          pInput = pinput;
          Dimmension.SetDimmensionLength(0,size);
          pMasterResource = NULL;
        }
        Descriptor( Rendering::Layout::Declaration *pinput, Rendering::ITexture *presource , Rendering::Layout::Dimmension *dimmension )
        {
          Type = RT_Texture;
          pInput = pinput;
          Dimmension = *dimmension;
          pMasterResource = NULL;
        }
        // Sub Resources:
        Descriptor( Rendering::IBuffer *presource, UINT64 size )
        {
          Type   = RT_SubBuffer;
          pInput = NULL;
          pMasterResource = (Rendering::Render::IResource *) presource;
          Dimmension.SetDimmensionLength(0,size);
        }
      };
    }
    class IResource : public Mapping::IMappable
    {
    public:
      virtual Resource::Type GetType()=0;
      virtual ~IResource() { };
    };
    class IResourceConfigurator { public: virtual ~IResourceConfigurator(){ }; };
    class BufferConfigurator : public IResourceConfigurator
    {
    public:
      Layout::Declaration input;
      Layout::Dimmension dimmension;
      IBuffer *pParentBuffer;
    public:
      BufferConfigurator( Layout::UsageGroup group, UINT64 size ):pParentBuffer(NULL) { input.SetUsageGroup(group); dimmension.at(0) = size;  }
      BufferConfigurator( IBuffer *pparent, UINT64 size ):pParentBuffer(pparent) { input.Reset(); dimmension.at(0) = size; }
    };
    class TextureConfigurator : public IResourceConfigurator
    {
    public:
      Layout::Declaration input;
      Layout::Dimmension dimmension;
    public:
      TextureConfigurator( Layout::Format format, UINT64 sizeU, UINT64 sizeV ) { input.SetFormat(format); dimmension.at(0) = sizeU; dimmension.at(1) = sizeV; }
    };
    class IResourceFactory
    {
    public:
      virtual IBuffer*   CreateBuffer    ( Layout::Declaration &input, UINT64 elementCount )=0;  
      virtual IBuffer*   CreateSubBuffer ( Rendering::IBuffer *pmaster, UINT64 elementCount )=0;
      virtual ITexture*  CreateTexture   ( Layout::Declaration &input, Layout::Dimmension &dimmension )=0;   
      virtual ILayout*   CreateLayout    ( Layout::Descriptor &descriptor )=0;
      //
      virtual bool CreateResource ( Resource::Descriptor *descriptor, IResource **ppResource )=0;
      virtual bool CreateResource ( IResourceConfigurator *configurator, IResource **ppResource )=0;
      virtual bool DestroyResource( IResource **ppResource )=0;
    };
  }
  
  class IBuffer : public Rendering::Render::IResource
  {
  public:  
    virtual bool  SetData( void* ptr, UINT64 size )=0;
    virtual bool  GetData( void* ptr, UINT64 size )=0;
    /*
    virtual bool  SetData( Buffer::Topology topology, void* ptr, UINT64 size )=0;
    virtual bool  GetData( Buffer::Topology topology, void* ptr, UINT64 size )=0;
    */
    virtual Buffer::Descriptor GetDescriptor()=0;
    // SubBuffers:
    //virtual IBuffer* CreateSubBuffer(UINT64 elements_count)=0;
    virtual vector<IBuffer*>* GetSubBuffers()=0;
    //
    virtual ~IBuffer() { };
  };
  class ITexture : public Render::IResource
  {
  public:  
    virtual bool SetLod( UINT64 lod )=0;
    virtual bool SetData( void* ptr, UINT64 size )=0;
    virtual bool GetData( void* ptr, UINT64 size )=0;
    virtual Texture::Desctiptor GetDescriptor()=0;
    virtual ~ITexture() { };
  };
  class IEffect : public Render::IResource
  {
  public:  
  
    //virtual bool SetParameter(const char* param, const ITexture *val)=0;
    //virtual bool SetParameter(const char* param, const D3DXMATRIXA16 *val)=0;
    virtual bool SetParameter(UINT64 parameter_id, vector<float> *parameter)=0;
    virtual bool SetParameter(UINT64 parameter_id, float *parameter)=0;
    virtual bool SetParameter(UINT64 parameter_id, ITexture *parameter)=0;
    virtual bool SetParameter(UINT64 parameter_id, D3DXMATRIXA16 *parameter)=0;
        
    //virtual bool SetTechnique(const char* technique)=0;
    virtual bool BeginTechnique(UINT64 technique_id)=0;
    virtual bool EndTechnique()=0;
    virtual bool BeginPass(UINT64 technique_id)=0;
    virtual bool EndPass()=0;

    virtual vector<Effect::ParameterDescriptor>* GetParameters()=0;
    virtual vector<Effect::TechniqueDescriptor>* GetTechniques()=0;
    
    virtual ~IEffect() { };
    
  };  
  class ILayout : public Render::IResource
  {
  public:
    virtual Layout::Descriptor* GetDescriptor()=0;
  };

  class IRender : public Render::IResourceFactory, public Mapping::IMapper
  {
  public:
    virtual ITexture*  CreateTexture ( wstring str )=0;
    virtual IEffect*   CreateEffect  ( wstring str )=0;
    /*
    virtual bool Map( IResource* presource, Render::Mapping::Descriptor *pDescriptor )=0;
    virtual bool Unmap( IResource* presource )=0;
    
    virtual bool Map( IBuffer* pBuffer, Render::Mapping::Descriptor *pDescriptor )=0;
    virtual bool Unmap( IBuffer* pBuffer )=0;
    */
    virtual bool Clear ( )=0;
    virtual bool Begin ( )=0;
    virtual bool SetBuffer ( UINT64 input_id , IBuffer* parameter )=0;
    virtual bool SetLayout ( ILayout *layout )=0;
    virtual bool SetTopology  ( Buffer::Topology topology )=0;
    virtual bool DrawVertexes ( )=0;
    virtual bool DrawIndexes  ( )=0;
    virtual bool Finish ( )=0;

    virtual ~IRender() { };
  };

}

#endif /* IRENDER */